package com.example.sentinel.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.example.sentinel.exception.R;
import com.example.sentinel.sentinel.MyDegraded;
import com.example.sentinel.sentinel.MyFlowRule;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * sentinel实现流控
 */
@RequestMapping("/sentinel")
@RestController
public class FlowRuleController {

    /**
     * 测试流控
     *  @SentinelResource 此注解是用来指定当前方法做降级的，value为接口的资源名称，blockHandler为限流进入的的方法,blockHandlerClass对应限流方法所在位置
     */
    @GetMapping("/flowRule/one")
    @SentinelResource(value = "flowRuleOne",blockHandlerClass = MyFlowRule.class,blockHandler = "flowRuleWay")
    public R flowRule(){
      return R.success(200,"访问成功");
    }

    /**
     * 测试降级
     *  @SentinelResource 此注解是用来指定当前方法做降级的，value为接口的资源名称，blockHandler为降级的方法,blockHandlerClass对应降级方法所在位置
     * @return
     */
    @GetMapping("/degraded/one")
    @SentinelResource(value = "degradedOne",blockHandlerClass = MyDegraded.class,blockHandler = "degradedRuleWay")
    public R degraded(){
        int a=1/0;
        return R.success(200,"访问成功");
    }



    /**
     * 配置流控规则
     */
    @PostConstruct
    public static void initflowRule(){
        //创建降级规则集合
        List<FlowRule> rules = new ArrayList<>();

         FlowRule rule = new FlowRule();
         //设置受保护的资源
         rule.setResource("flowRuleOne");
        // 设置流控规则 QPS（每秒访问的次数规则）
         rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
         // 设置受保护的资源阈值（2次）
         rule.setCount(2);
         rules.add(rule);


         // 加载配置好的规则（若有多个就再创建rule去配置就行了）
         FlowRuleManager.loadRules(rules);
    }

    /**
     * 降级规则
     */
    @PostConstruct
    private static void initDegradeRule() {
        //创建降级规则集合
        List<DegradeRule> rules = new ArrayList<DegradeRule>();

        DegradeRule rule = new DegradeRule();
        //设置受保护的资源
        rule.setResource("degradedOne");

        //设置断路策略(异常次数)
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        //错误阈值
        rule.setCount(2);
        //设置断路器恢复时间（10S）
        rule.setTimeWindow(10);
        //设置最小请求次数
        rule.setMinRequestAmount(2);
        //时间阈值（单位毫秒）
        rule.setStatIntervalMs(60*1000);

        //总结规则：在1分钟内，请求异常次数达到2次，则进入降级方法，10s后才恢复该方法

        rules.add(rule);

        // 加载配置好的规则（若有多个就再创建rule去配置就行了）
        DegradeRuleManager.loadRules(rules);
    }
}
